<template>
  <div class="ThreeDemo">
    <!-- 加载提示 -->
    <div class="maskLoading" v-if="isLoading">
      <div class="loading">
        <div :style="{ width: loadingWidth + '%' }"></div>
      </div>
      <div style="padding-left: 10px">{{ parseInt(loadingWidth) }}%</div>
    </div>
    <!-- 位置信息及操作按钮 -->
    <div class="mask">
      <p>x : {{ x }} y:{{ y }} z :{{ z }}</p>
      <button @click="Three.autoRotation">转动车</button>
      <button @click="Three.autoRotation(false)">停止</button>
      <div class="flex">
        <div
          @click="setCarColor(item)"
          v-for="(item, index) in colorAry"
          :style="{ backgroundColor: item }"
          :key="index"
        ></div>
      </div>
    </div>
  </div>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// import { GUI } from "dat.gui";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";

export default {
  name: "Home",
  props: {
    msg: String,
  },
  data() {
    return {
      Three: {},
      colorAry: [
        "rgb(216, 27, 67)",
        "rgb(142, 36, 170)",
        "rgb(81, 45, 168)",
        "rgb(48, 63, 159)",
        "rgb(30, 136, 229)",
        "rgb(0, 137, 123)",
        "rgb(67, 160, 71)",
        "rgb(251, 192, 45)",
        "rgb(245, 124, 0)",
        "rgb(230, 74, 25)",
        "rgb(233, 30, 78)",
        "rgb(156, 39, 176)",
        "rgb(0, 0, 0)",
      ], // 车身颜色数组
    };
  },
  computed: {
    isLoading() {
      return this.Three.isLoading;
    },
    loadingWidth() {
      return this.Three.loadingWidth;
    },
    x() {
      return this.Three.x;
    },
    y() {
      return this.Three.y;
    },
    z() {
      return this.Three.z;
    },
  },
  async created() {
    //加载模型
    function loadFile(url) {
      const loader = new GLTFLoader(); //引入模型的loader实例
      return new Promise((resolve, reject) => {
        loader.load(
          url,
          (gltf) => {
            resolve(gltf);
          },
          ({ loaded, total }) => {
            let load = Math.abs((loaded / total) * 100);
            this.loadingWidth.value = load;
            if (load >= 100) {
              setTimeout(() => {
                this.isLoading.value = false;
              }, 1000);
            }
            console.log((loaded / total) * 100 + "% loaded");
          },
          (err) => {
            reject(err);
          }
        );
      });
    }
    async function init() {
      // create a scene, that will hold all our elements such as objects, cameras and lights.
      let scene = new THREE.Scene();
      // create a camera, which defines where we're looking at
      let camera = new THREE.PerspectiveCamera(
        75,
        window.innerWidth / window.innerHeight,
        0.1,
        100
      );
      // tell the camera where to look
      camera.position.set(0, 0, 10);
      // create a render and set the size
      const sizes = {
        width: window.innerWidth,
        height: window.innerHeight,
      };

      // 创建几何体
      const homeObj = new THREE.Object3D();
      homeObj.position.set(0, 0, 0);
      scene.add(homeObj);

      const geometry = new THREE.CylinderGeometry(1, 1.5, 1, 80);
      const material = new THREE.MeshPhongMaterial({
        // color: 0xffff00,
        // emissive: 0xffff00,
      });
      const mesh = new THREE.Mesh(geometry, material);

      // 设置灯光
      // class DegRadHelper {
      //   constructor(obj, prop) {
      //     this.obj = obj;
      //     this.prop = prop;
      //   }
      //   get value() {
      //     return THREE.MathUtils.radToDeg(this.obj[this.prop]);
      //   }
      //   set value(v) {
      //     this.obj[this.prop] = THREE.MathUtils.degToRad(v);
      //   }
      // }
      // class ColorGUIHelper {
      //   constructor(object, prop) {
      //     this.object = object;
      //     this.prop = prop;
      //   }
      //   get value() {
      //     return `#${this.object[this.prop].getHexString()}`;
      //   }
      //   set value(hexString) {
      //     this.object[this.prop].set(hexString);
      //   }
      // }

      {
        const color = 0xffcc66;
        const intensity = 2;
        const light = new THREE.SpotLight(color, intensity);
        light.position.set(2, 6, 2);
        // light.target.position.set(-5, 0, 0);
        scene.add(light);
        scene.add(light.target);

        const helper = new THREE.SpotLightHelper(light);
        scene.add(helper);

        // function updateLight() {
        //   light.target.updateMatrixWorld();
        //   helper.update();
        // }
        // updateLight();

        // const gui = new GUI();
        // gui.addColor(new ColorGUIHelper(light, "color"), "value").name("color");
        // gui.add(light, "intensity", 0, 2, 0.01);
        // gui.add(light, "distance", 0, 40).onChange(updateLight);
        // gui
        //   .add(new DegRadHelper(light, "angle"), "value", 0, 90)
        //   .name("angle")
        //   .onChange(updateLight);
        // gui.add(light, "penumbra", 0, 1, 0.01);

        // makeXYZGUI(gui, vector3, name, onChangeFn) {
        //   const folder = gui.addFolder(name);
        //   folder.add(vector3, "x", -10, 10).onChange(onChangeFn);
        //   folder.add(vector3, "y", 0, 10).onChange(onChangeFn);
        //   folder.add(vector3, "z", -10, 10).onChange(onChangeFn);
        //   folder.open();
        // }

        // makeXYZGUI(gui, light.position, "position", updateLight);
        // makeXYZGUI(gui, light.target.position, "target", updateLight);
      }
      homeObj.add(mesh);

      const obj = new THREE.Object3D();
      homeObj.add(obj);

      const gltf = await loadFile("/static/3d/koala_con_flor/scene.gltf");
      obj.add(gltf.scene);
      obj.position.set(0, 0.5, 0);
      obj.scale.set(3, 3, 3);
      const axesHelper = new THREE.AxesHelper(2);
      obj.add(axesHelper);

      let renderer = new THREE.WebGLRenderer();
      renderer.setSize(sizes.width, sizes.height);
      // add the output of the render function to the HTML
      document.body.appendChild(renderer.domElement);

      // var clock = new THREE.Clock();
      // function for re-rendering/animating the scene
      function resizeRendererToDisplaySize(renderer) {
        const canvas = renderer.domElement;
        const width = canvas.clientWidth;
        const height = canvas.clientHeight;
        const needResize = canvas.width !== width || canvas.height !== height;
        if (needResize) {
          renderer.setSize(width, height, false);
        }
        return needResize;
      }
      function render(time) {
        time *= 0.001;
        if (resizeRendererToDisplaySize(renderer)) {
          const canvas = renderer.domElement;
          camera.aspect = canvas.clientWidth / canvas.clientHeight;
          camera.updateProjectionMatrix();
        }
        obj.rotation.y = time;
        renderer.render(scene, camera);
        requestAnimationFrame(render);
      }
      requestAnimationFrame(render);

      /**
       * 控制器
       */
      const controls = new OrbitControls(camera, renderer.domElement);
      controls.maxPolarAngle = (0.9 * Math.PI) / 2;
      controls.enableZoom = true;
      //  controls.addEventListener("change", this.render);

      /**
       * 使用dat.gui工具
       */
      // const gui = new dat.GUI({
      //   name: "lightGui", //GUI的名称
      // });
      // let guiControls = {
      //   x: 0,
      //   y: 0,
      //   z: 0,
      // };
      // gui.add(guiControls, "x", -100, 100, 0.1).onChange((e) => {
      //   camera.position.set(e, 0, 10);
      // });
      // gui.add(guiControls, "y", -100, 100, 0.1).onChange((e) => {
      //   camera.position.set(0, e, 10);
      // });
      // gui.add(guiControls, "z", -100, 100, 0.1).onChange((e) => {
      //   camera.position.set(0, 0, e);
      // });
    }
    init();
  },
  unmounted() {
    this.Three = null;
  },
  methods: {
    setCarColor(color) {
      this.Three.setModelColor(color, "mesh_0");
    },
  },
};
</script> 

<style lang="less" scoped>
.ThreeDemo {
  .maskLoading {
    background: #000;
    position: fixed;
    display: flex;
    justify-content: center;
    align-items: center;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    z-index: 1111111;
    color: #fff;
    .loading {
      width: 400px;
      height: 20px;
      border: 1px solid #fff;
      background: #000;
      overflow: hidden;
      border-radius: 10px;
      & > div {
        background: #fff;
        height: 20px;
        width: 0;
        transition-duration: 500ms;
        transition-timing-function: ease-in;
      }
    }
  }

  canvas {
    width: 100%;
    height: 100%;
    margin: 0;
  }

  .mask {
    color: #fff;
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    .flex {
      display: flex;
      flex-wrap: wrap;
      padding: 20px;
      & > div {
        width: 10px;
        height: 10px;
        margin: 5px;
        cursor: pointer;
      }
    }
  }
}
</style>
